<template>
  <ContentDetailWrap :title="t('action.add')">
    <template #header>
      <BaseButton @click="go(-1)">
        {{ t('common.back') }}
      </BaseButton>
      <BaseButton type="primary" :loading="loading" @click="submit">
        {{ t('action.save') }}
      </BaseButton>
    </template>

    <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
      <el-form-item :label="t('miner_firmwareVersion.pid')" class="w-80%" prop="pid">
        <el-input
          v-model="productsDisplayText"
          disabled
          :placeholder="'请选择' + t('miner_firmwareVersion.pid')"
        />
      </el-form-item>
      <el-form-item :label="t('miner_firmwareVersion.version_id')" class="w-80%" prop="version_id">
        <el-input
          v-model="form.version_id"
          :placeholder="'请输入' + t('miner_firmwareVersion.version_id')"
        />
      </el-form-item>
      <el-form-item
        :label="t('minescreenFirmwareVersion.firmwareVersion.firmware_download_addr')"
        prop="firmware_fileid"
        class="w-80%"
      >
        <el-upload
          class="w-100%"
          drag
          v-loading="uploading"
          :http-request="handleOssUpload"
          :on-remove="handleRemoveFile"
          :on-preview="handlePreview"
          :limit="1"
          :file-list="firmware_fileid_list"
        >
          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
          <div class="el-upload__text"> 拖拽到此处或<em>点击上传</em> </div>
          <template #tip>
            <div class="el-upload__tip"> 最多上传1个文件，文件大小不超过1024MB </div>
          </template>
        </el-upload>
      </el-form-item>
      <el-form-item
        :label="t('miner_firmwareVersion.release_date')"
        class="w-80%"
        prop="release_date"
      >
        <el-date-picker
          width="100%"
          v-model="form.release_date"
          type="date"
          value-format="YYYY-MM-DD"
          :placeholder="'请选择' + t('miner_firmwareVersion.release_date')"
        />
      </el-form-item>
    </el-form>

    <DialogProduct
      ref="DialogProductRef"
      @expose-multiple-data="getExposeProductData"
      :multiple="true"
      :pagination="false"
    />
  </ContentDetailWrap>
</template>

<script setup lang="ts">
import { ContentDetailWrap } from '@/components/ContentDetailWrap'
import { ElMessage, type FormInstance } from 'element-plus'
import { updateDataApi, getInfoApi } from '@/api/operations/miner_firmwareversion/index'
import DialogProduct from '@/components/Dialog/src/Product.vue'
import { useRouter, useRoute } from 'vue-router'
import { getOssDirectUploadParams, saveDirectUploadInfo } from '@/api/upload'
import type { UploadFile, UploadRequestOptions } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { createOssFilePath, createFileName } from '@/utils'

const { t } = useI18n()
const { push, go } = useRouter()

const route = useRoute()

const loading = ref<boolean>(false)
const uploading = ref(false)
const formRef = ref<FormInstance>()
const form = ref<Record<string, any>>({
  firmware_fileid: null,
  pid: '',
  version_id: '',
  release_date: ''
})
const productsDisplayText = ref('')
const firmware_fileid_list = ref<any[]>([]) // 附件列表

// 表单验证规则
const rules = {
  pid: [{ required: true, message: '请选择产品', trigger: 'change' }],
  version_id: [{ required: true, message: '请输入版本ID', trigger: 'blur' }],
  firmware_fileid: [{ required: true, message: '请上传固件文件', trigger: 'change' }],
  release_date: [{ required: true, message: '请选择发布日期', trigger: 'change' }]
}

const DialogProductRef = ref<any>(null)

const handleOpenMining = () => {
  console.log('form.value.pids', form.value.pids)
  nextTick(() => {
    DialogProductRef!.value!.dialogVisible = true
    // 将pids字符串拆分成对象数组
    const selectedProducts = form.value.pids
      ? form.value.pids.split(',').map((id: string) => ({ id: parseInt(id.trim()) }))
      : []
    DialogProductRef!.value!.initialize(selectedProducts)
  })
}

const getExposeProductData = (val: any) => {
  form.value.pid = val.map((item: any) => item.id).join(',')
  productsDisplayText.value = val.map((item: any) => item.cname).join(',')
  // 清除产品字段的验证错误
  formRef.value?.clearValidate('pid')
}

const handleRemoveFile = () => {
  form.value.firmware_fileid = null
  // 重新验证固件文件字段以显示错误提示
  formRef.value?.validateField('firmware_fileid')
}

// 点击文件列表中已上传的文件时的钩子
const handlePreview = (file: UploadFile) => {
  const previewUrl = file.url || (file.raw as any)?.url
  if (previewUrl) {
    window.open(previewUrl, '_blank')
  }
}

// 自定义上传到阿里云 OSS
const handleOssUpload = async (options: UploadRequestOptions) => {
  uploading.value = true
  const { file } = options
  try {
    // 获取文件扩展名
    const fileExtension = file.name.split('.').pop() ?? ''

    // 1. 从后端获取直传参数
    const paramsRes: any = await getOssDirectUploadParams({ directory: 7 }) // 目录7代表固件
    if (paramsRes.code !== 0) {
      ElMessage.error('获取上传参数失败: ' + (paramsRes.message || '未知错误'))
      throw new Error('获取上传参数失败')
    }
    const ossParams = paramsRes.data
    const fileName = createFileName(fileExtension)
    const ossFilePath = createOssFilePath(fileName, ossParams.directory)

    // 前端文件大小校验
    if (file.size > ossParams.max_file_size) {
      const err_msg = `文件大小不能超过 ${ossParams.max_file_size / 1024 / 1024} MB`
      ElMessage.error(err_msg)
      const err = new Error(err_msg) as any
      err.status = 400
      err.method = 'POST'
      err.url = ossParams.host
      options.onError(err)
      return
    }

    // 2. 构造 FormData 并上传到阿里云
    const formData = new FormData()
    formData.append('key', ossFilePath)
    formData.append('policy', ossParams.policy)
    formData.append('OSSAccessKeyId', import.meta.env.VITE_ALIYUN_OSS_ACCESS_KEY_ID as string)
    formData.append('success_action_status', '200')
    formData.append('signature', ossParams.signature)
    formData.append('file', file)

    let response: Response | undefined
    try {
      response = await fetch(ossParams.host, {
        method: 'POST',
        body: formData
      })
    } catch (err) {
      console.log('err', err)
      response = undefined
    }
    if (!response || !response.ok) {
      const errorText = response ? await response.text() : '网络异常或无响应'
      console.error('OSS 上传失败，状态码:', response ? response.status : '无响应')
      console.error('OSS 错误内容:', errorText)
      ElMessage.error('OSS上传失败，详细错误见控制台')
      throw new Error('OSS上传失败: ' + errorText)
    }

    // 上传成功, 构造可预览的 URL
    const fileUrl = `${ossParams.host}/${ossFilePath}`

    // 3. 上传成功后，通知后端保存文件信息
    const saveRes: any = await saveDirectUploadInfo({
      name: file.name,
      directory: 7,
      url: ossFilePath
    })

    if (saveRes.code !== 0) {
      ElMessage.error('保存文件信息失败: ' + (saveRes.message || '未知错误'))
      throw new Error('保存文件信息失败')
    }

    // 4. 将文件ID保存到表单中, 并将最终URL附加到文件对象上
    form.value.firmware_fileid = saveRes.data.id
    ;(options.file as any).url = fileUrl

    // 5. 通知 el-upload 组件上传成功
    options.onSuccess(saveRes.data)

    ElMessage.success('上传成功！')
    formRef.value?.clearValidate('firmware_fileid')
  } catch (error) {
    console.error('上传失败:', error)
    ElMessage.error('上传失败，请检查控制台日志。')
    // 手动触发上传失败的回调
    options.onError(error as any)
    // 如果需要，可以从文件列表中移除失败的文件
  } finally {
    uploading.value = false
  }
}

const submit = async () => {
  // 使用表单验证
  if (!formRef.value) return

  try {
    await formRef.value.validate()
    loading.value = true
    const resp = await updateDataApi({
      id: route.query.id as string,
      firmware_fileid: form.value.firmware_fileid,
      pid: form.value.pid,
      version_id: form.value.version_id,
      release_date: form.value.release_date
    })
    if (resp.code === 0) {
      loading.value = false
      ElMessage.success('编辑成功')
      push('/oaperations/firmwareversion')
    }
  } catch (error) {
    loading.value = false
    if (error !== false) {
      console.error('提交失败:', error)
    }
  }
}

const getDetail = async () => {
  const resp = await getInfoApi(route.query.id as string)
  form.value = resp.data
  productsDisplayText.value = resp.data.pid_name
  firmware_fileid_list.value = resp.data.firmware_fileid_list.map((item: any) => ({
    id: item.id,
    name: item.name,
    url: item.url
  }))
}

onMounted(async () => {
  await getDetail()
})
</script>

<style lang="less" scoped></style>
